﻿using MvvmCross.Wpf.Views;
using Sidvall.UI.Views;
using Sidvall.WorkItemManager.UI.ViewModels;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Threading;

namespace Sidvall.WorkItemManager.UI.Wpf.Views
{
    public partial class WorkerView : MvxWpfView, IView, IViewModelProvider
    {
        #region Public Members

        public new WorkerViewModel ViewModel
        {
            get
            {
                return (WorkerViewModel)base.ViewModel;
            }
            set
            {
                base.ViewModel = value;
            }
        }

        Sidvall.UI.ViewModels.IViewModel IViewModelProvider.ViewModel
        {
            get
            {
                return this.ViewModel;
            }
        }

        #endregion
        #region Constructors

        public WorkerView()
        {
            InitializeComponent();
        }

        #endregion

        #region IView Members

        Task IView.OnViewEventAsync(ViewEventArgs args)
        {
            switch (args.EventType)
            {
                case ViewEventType.ViewCreated:
                    if (this.Timer == null)
                    {
                        this.Timer = new System.Windows.Threading.DispatcherTimer();
                        this.Timer.Tick += OnTimerTick;
                        this.Timer.Interval = new System.TimeSpan(0, 0, GetRefreshRate());
                        this.Timer.Start();
                    }
                    break;
                case ViewEventType.ViewUnloaded:
                    if (this.Timer != null)
                    {
                        this.Timer.Stop();
                        this.Timer = null;
                    }
                    break;
                default:
                    break;
            }
            return Task.FromResult(true);
        }

        #endregion
        #region Drag & Drop

        private Point StartPoint { get; set; }

        private void WorkerGrid_PreviewMouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            this.StartPoint = e.GetPosition(null);
        }
        private void WorkerGrid_MouseMove(object sender, System.Windows.Input.MouseEventArgs e)
        {
            Sidvall.WorkItemManager.UI.Entities.TreeItem item;
            Vector diff;
            Point mousePoint;
            DataGridRow row;

            mousePoint = e.GetPosition(null);
            diff = this.StartPoint - mousePoint;
            if ((e.LeftButton == System.Windows.Input.MouseButtonState.Pressed) &&
                (System.Math.Abs(diff.X) > SystemParameters.MinimumHorizontalDragDistance || System.Math.Abs(diff.Y) > SystemParameters.MinimumVerticalDragDistance))
            {
                row = Sidvall.UI.Wpf.ControlManager.FindParentControl<DataGridRow>((DependencyObject)e.OriginalSource);
                if (row == null)
                    return;
                item = row.Item as Sidvall.WorkItemManager.UI.Entities.TreeItem;
                if (item == null)
                    return;
                if (!item.IsItem)
                    return;
                DragDrop.DoDragDrop(this.WorkerGrid, item, DragDropEffects.Move | DragDropEffects.Copy);
            }
        }
        private void WorkerGrid_DragOver(object sender, DragEventArgs e)
        {
            DropItem item;

            e.Handled = true;
            item = GetDropItem(sender, e);
            e.Effects = item.Effects;
        }
        private async void WorkerGrid_Drop(object sender, DragEventArgs e)
        {
            DropItem item;

            e.Handled = true;
            item = GetDropItem(sender, e);
            if (item.Effects != DragDropEffects.None)
                await this.ViewModel.MoveTreeItemAsync(item.SourceItem, item.DestinationItem);
        }
        private DropItem GetDropItem(object sender, DragEventArgs e)
        {
            DropItem item;
            DataGridRow row;

            item = new DropItem()
            {
                Effects = DragDropEffects.None,
            };
            item.SourceItem = e.Data.GetData(typeof(Sidvall.WorkItemManager.UI.Entities.TreeItem)) as Sidvall.WorkItemManager.UI.Entities.TreeItem;
            if (item.SourceItem == null)
                return item;
            row = Sidvall.UI.Wpf.ControlManager.FindParentControl<DataGridRow>((UIElement)sender, e.GetPosition(this.WorkerGrid));
            if (row == null)
                return item;
            item.DestinationItem = row.Item as Sidvall.WorkItemManager.UI.Entities.TreeItem;
            if (item.DestinationItem == null)
                return item;
            if ((!item.DestinationItem.IsItem) && (!item.DestinationItem.IsWorker))
                return item;
            if (item.DestinationItem.TreeItemId == item.SourceItem.TreeItemId)
                return item;
            if (item.DestinationItem.ServerConnectionId == item.SourceItem.ServerConnectionId)
                item.Effects = DragDropEffects.Move;
            else
                item.Effects = DragDropEffects.Copy;
            return item;
        }
        private class DropItem
        {
            public DragDropEffects Effects { get; set; }
            public Sidvall.WorkItemManager.UI.Entities.TreeItem SourceItem { get; set; }
            public Sidvall.WorkItemManager.UI.Entities.TreeItem DestinationItem { get; set; }
        }

        #endregion
        #region Timer

        private DispatcherTimer Timer { get; set; }

        private async void OnTimerTick(object sender, System.EventArgs e)
        {
            if (this.ViewModel != null)
                await this.ViewModel.ReloadAsync();
        }
        private int GetRefreshRate()
        {
            if (this.txtRefreshRate.Value != null)
                return this.txtRefreshRate.Value.Value;
            return 2;
        }
        private void txtRefreshRate_ValueChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
        {
            if (this.Timer == null)
                return;
            this.Timer.Stop();
            this.Timer.Interval = new System.TimeSpan(0, 0, GetRefreshRate());
            this.Timer.Start();
        }

        #endregion
    }
}
